import java.io.{BufferedReader, FileReader}
import java.sql.{Connection, DriverManager, PreparedStatement, ResultSet}
import scala.io.{BufferedSource, Source}

object Demo02ScalaBase {
  def main(args: Array[String]): Unit = {
    // 注释
    // 单行注释
    /**
     * 多行注释 用于 文档说明
     */

    // 变量的定义
    /**
     * val 修饰的变量是不可以重新赋值的
     * var 修饰的变量可以重新赋值
     * 变量的类型可以有编译器自行推断，也可以手动指定
     */
    val i = 10
    var j = 20

    println(i)
    println(j)
    // 重新赋值
    //    i = 100 // i由于是val修饰的 所以不能修改
    j = 200
    println(j)

    // Scala中的数据类型
    println(i.isInstanceOf[Int])

    val b: Byte = 1
    val s: Short = 1
    val i2: Int = 1
    val l: Long = 1L
    val f: Float = 1.23456F
    val d: Double = 1.23456D
    val c: Char = 'a'
    val bool1: Boolean = true
    val bool2: Boolean = false

    println(b, s, i2, l, f, d, c, bool1, bool2)

    /**
     * Any类型有两个子类分别是：AnyRef、AnyVal
     * AnyVal是所有值的类型的父类
     * AnyRef是所有引用类型（类）的父类
     */

    /**
     * Scala中的字符串实际上是基于Java的String
     */
    val str1: String = "hello world"
    // AnyRef类似Java中的Object
    val anyRef: AnyRef = str1

    /**
     * Scala中的打印方法同Java方法一致
     */
    System.out.println(anyRef)
    println(anyRef)

    // 字符串常用的方法
    /**
     * 因为Scala的String基于Java中的String
     * 所以Java中的跟String有关的方法都可以在Scala中使用
     */
    val strArr: Array[String] = str1.split(" ")
    println(strArr.mkString(","))
    // Scala中的String类型还有一些方法是在Scala当中特有的
    /**
     * 隐式转换：动态的给对象增加方法
     */
    str1.foreach(println)

    // 类型转换
    // Java版本
    val int1: Int = 100
    // Int2Str
    val int2Str: String = String.valueOf(int1)
    println(int2Str)
    val s2: String = "200"
    val string2Int: Integer = Integer.valueOf(s2)
    println(string2Int)

    // Scala版本
    /**
     * 底层都是基于Java的方法
     * 在这之上能够简化调用
     */
    val s3: String = "123"
    println(s3.toByte)
    println(s3.toShort)
    println(s3.toInt)
    println(s3.toLong)
    println(s3.toFloat)
    println(s3.toDouble)
    println("true".toBoolean)
    println(10.toString)

    // 拼接字符串
    val hello: String = "hello"
    val space: String = " "
    val world: String = "world"

    val concatStr1: String = hello + space + world
    val builder = new StringBuilder()
    builder.append(hello)
    builder.append(space)

    builder append world

    println(concatStr1)
    println(builder)

    // Scala中的拼接
    val concatStr2: String = s"$hello,$space,$world"
    println(concatStr2)

    // 在使用Scala的拼接方式时需要注意变量的名称
    // 如果是以下划线开头的变量名需要加上{}
    val _str4: String = "!"
    println(s"$hello$space$world${_str4}")

    val sqlStr1: String = "select * from (" +
      "select * " +
      "from tb1 " +
      "left join tb2 " +
      "on tb1.id = tb2.id" +
      ") t1"

    val sqlStr2: String =
      """
        |select *
        |from (
        | select *
        | from tb1
        | left join tb2
        | on tb1.id = tb2.id
        |) t1
        |""".stripMargin

    println(sqlStr1)
    println(sqlStr2)

    println(9 * 9) // 81 这里的 *号是普通的运算符
    println("#" * 50) // 50个#号

    // 算术运算
    println(10 + 2)
    println(10 - 2)
    println(10 * 2)
    println(10 / 2)
    println(10 % 2)
    // 逻辑运算 & | !
    val b1: Boolean = true
    val b2: Boolean = false
    println(b1 & b2)
    println(b1 | b2)
    println(!b1)

    // 选择结构
    val age: Int = -1
    if (age < 0 | age > 200) {
      println("不是正常人")
    } else if (age >= 18) {
      println("成年")
    } else {
      println("未成年")
    }

    // 循环结构
    // 计算1~100的累加和
    var cnt: Int = 1
    var sum: Int = 0
    // while do 只有当条件成立 才会执行循环体
    while (cnt <= 100) {
      sum = sum + cnt
      cnt += 1
    }
    println(sum)

    cnt = 1
    sum = 0
    // do while 不管条件成不成立 都会执行循环体
    do {
      sum += cnt
      cnt += 1
    } while (cnt <= 100)
    println(sum)

    // for 循环 同Python非常类似 主要用于遍历数组、collection
    // 类似Java中的for each
    val line: String = "1,2,3,4,5,6,7"
    val words: Array[String] = line.split(",")
    for (word <- words) {
      println(word)
    }


    // 读写文件
    // Java版
    val br: BufferedReader = new BufferedReader(new FileReader("Scala/data/students.txt"))
    var sLine: String = br.readLine()
    while (sLine != null) {
      println(sLine)
      sLine = br.readLine()
    }
    br.close()

    // Scala版
    val bs: BufferedSource = Source
      .fromFile("Scala/data/students.txt")
    val strings: Iterator[String] = bs.getLines()
    for (elem <- strings) {
      println(elem)
    }
    bs.close()

    // 简化版
    // 链式调用
    val bs2: BufferedSource = Source
      .fromFile("Scala/data/students.txt")

    bs2.getLines()
      .foreach(println)

    bs2.close()

    // Scala中没有特殊的写文件的方式
    //    PrintWriter
    //    FileWriter

    // 怎么在Scala代码中读取MySQL中的数据

    // 1、建立连接
    val conn: Connection = DriverManager.getConnection("jdbc:mysql://master:3306/student?useSSL=false", "root", "123456")

    // 2、创建一个Statement
    val pSt: PreparedStatement = conn.prepareStatement("select id,name,age,gender,clazz from student where clazz like ?")

    // 3、设置参数
    pSt.setString(1, "文科%")

    // 4、执行SQL 并获取结果
    val rs: ResultSet = pSt.executeQuery()
    while (rs.next()) {
      val id: Int = rs.getInt("id")
      val name: String = rs.getString("name")
      val age: Int = rs.getInt("age")
      val gender: String = rs.getString("gender")
      val clazz: String = rs.getString("clazz")

      println(s"$id,$name,$age,$gender,$clazz")

    }
    // 5、关闭连接
    rs.close()
    pSt.close()
    conn.close()

  }

}
